using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Security.Permissions;
using Microsoft.Win32;

using Banshee.Base;
using Banshee.Configuration;
namespace Banshee.Configuration
{
    [assembly: RegistryPermissionAttribute(SecurityAction.RequestMinimum,
        ViewAndModify = "HKEY_CURRENT_USER")]
    public class RegistryConfigurationClient : IConfigurationClient
    {

        const string userRoot = "HKEY_CURRENT_USER";
        const string subkey = "Software\\banshee";
        const string base_key = subkey;

        RegistryKey client = Registry.CurrentUser.CreateSubKey(subkey);

        private string CreateKeyPart(string part,bool node)
        {
            lock (((ICollection)key_table).SyncRoot)
            {
                if (!key_table.ContainsKey(part))
                {
                    key_table.Add(part, StringUtil.CamelCaseToUnderCase(part));
                    if(node)
                        client.CreateSubKey(part);
                }

                return key_table[part];
            }
        }

        public string CreateKey(string namespce, string key)
        {
            return namespce == null
                ? base_key + CreateKeyPart(key,false)
                : base_key + CreateKeyPart(namespce.Replace(".", @"\"),true) + @"\" + CreateKeyPart(key,false);
        }
        private Dictionary<string, string> key_table = new Dictionary<string, string>();

        public static string BaseKey
        {
            get { return base_key; }
        }
        #region IConfigurationClient Members

        public T Get<T>(SchemaEntry<T> entry)
        {
            return Get<T>(entry.Namespace, entry.Key, entry.DefaultValue);
        }

        public T Get<T>(SchemaEntry<T> entry, T fallback)
        {
            return Get<T>(entry.Namespace, entry.Key, fallback);
        }

        public T Get<T>(string key, T fallback)
        {
            return Get<T>(null, key, fallback);
        }

        public T Get<T>(string namespce, string key, T fallback)
        {
            try
            {
                RegistryKey readkey = client.OpenSubKey(namespce);
                object value = readkey.GetValue(key);
                if (value.ToString() == "True" || value.ToString() == "False")
                {
                    object val = Convert.ToBoolean(value.ToString().ToLower());
                    value = val;
                }
                return (T)value;
            }
            catch (Exception ex)
            {
                client.CreateSubKey(namespce);
                return fallback;
            }
        }

        public void Set<T>(SchemaEntry<T> entry, T value)
        {
            Set<T>(entry.Namespace, entry.Key, value);
        }

        public void Set<T>(string key, T value)
        {
            Set<T>(null, key, value);
        }

        public void Set<T>(string namespce, string key, T value)
        {
            if (client == null)
            {
                client = Registry.CurrentUser.CreateSubKey(base_key);
            }
            if (!string.IsNullOrEmpty(namespce))
            {
                string subkey = CreateKey(namespce, key);
                RegistryKey regkey = client.CreateSubKey(namespce);
                regkey.SetValue(key, value);
                
            }
            else
                client.SetValue(key, value);
        }

        #endregion
    }
}
